﻿''' <summary>
''' cmd /param1 /paramN arg1 argN
''' </summary>
''' <remarks></remarks>
Public Class command : Inherits MarshalByRefObject
    Private _cmdValue As String = ""
    Private _paramsValue As New SortedDictionary(Of String, String)
    Private _argsValue As New SortedDictionary(Of String, String)
    Private _cmdformatValue As String
    Private _description As String
    Private _funcVal As String
    Private _actionTypeVal As Char
    Public Event exec(ByRef params() As String, ByRef args() As String)
    ''' <summary>
    ''' List of registered commands
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared cmdList As New Dictionary(Of String, command)
    ' Private field to store time object instance was created.
    Private ReadOnly mdteCreationTime As DateTime = Date.Now
#Region "Constructors"
    'Default no argument constructor
    Public Sub New()
        MyBase.New()
    End Sub

    'Parameterized Constructor called only by Client Activated Objects
    Public Sub New(ByVal NewCmd As String)
        Me.cmd = NewCmd
        cmdList.Add(NewCmd, Me)
    End Sub
    Public Sub New(ByVal NewCmd As String, ByVal description As String, Optional ByVal params(,) As String = Nothing, Optional ByVal args(,) As String = Nothing)
        Me.cmd = NewCmd
        Me.description = description
        If (params IsNot Nothing) Then
            convert_arrayTo_kvp(params, Me._paramsValue)
        End If
        If (args IsNot Nothing) Then
            convert_arrayTo_kvp(args, Me._argsValue)
        End If
        If (cmdList.ContainsKey(NewCmd)) Then
            _error.printerror(String.Format("Command '{0}' could not be registerd because it a command with the same name already exists", NewCmd), False, False)
        Else
            cmdList.Add(NewCmd, Me)
        End If

    End Sub
#End Region
#Region "Dynamic Constructors"
    Public Shared Sub registerCommand(ByVal NewCmd As String)
        Dim tempcmd As New command(NewCmd)
    End Sub
    Public Shared Sub registerCommand(ByVal NewCmd As String, ByVal description As String, Optional ByVal params(,) As String = Nothing, Optional ByVal args(,) As String = Nothing)
        Dim tempcmd As New command(NewCmd, description, params, args)
    End Sub
#End Region
#Region "properties"
    Public Property cmd() As String
        Get
            Return _cmdValue
        End Get
        Set(ByVal Value As String)
            _cmdValue = Value
        End Set
    End Property
    Public Property params() As SortedDictionary(Of String, String)
        Get
            Return _paramsValue
        End Get
        Set(ByVal Value As SortedDictionary(Of String, String))
            _paramsValue = Value
        End Set
    End Property
    Public Property args() As SortedDictionary(Of String, String)
        Get
            Return _argsValue
        End Get
        Set(ByVal Value As SortedDictionary(Of String, String))
            _argsValue = Value
        End Set
    End Property
    Public ReadOnly Property syntax() As String
        'Usage:     rar <command> -<switch 1> -<switch N> <archive> <files...>
        '      <@listfiles...> <path_to_extract\>
        Get
            Return _cmdformatValue
        End Get
    End Property
    Public Property description() As String
        Get
            Return _description
        End Get
        Set(ByVal value As String)
            _description = value
        End Set
    End Property
    Public Property func() As String
        Get
            Return _funcVal
        End Get
        Set(ByVal value As String)
            _funcVal = value
        End Set
    End Property

#End Region
    Public Sub main(Optional ByVal params() As String = Nothing, Optional ByVal args() As String = Nothing)
        RaiseEvent exec(params, args)
    End Sub
    ''' <summary>
    ''' generates the command line syntax and format for this command
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub generateCMDformat()
        Me._cmdformatValue = ""

        If (Me.params.Count > 1) Then
            'Me._cmdformatValue += " /<param 1> /<param N>"
            For Each para As KeyValuePair(Of String, String) In Me.params
                Me._cmdformatValue += String.Format(" /<{0}>", para.Key)
            Next para
        ElseIf (Me.params.Count = 1) Then
            Me._cmdformatValue += String.Format(" [/{0}]", Me.params.ElementAt(0).Key)
        End If
        If (Me.args.Count >= 1) Then
            For Each arg As KeyValuePair(Of String, String) In Me.args
                Me._cmdformatValue += String.Format(" <{0}>", arg.Key)
            Next arg
        End If
    End Sub
    ''' <summary>
    ''' generates the man page for this command
    ''' </summary>
    ''' <returns>returns the man page as a string</returns>
    ''' <remarks></remarks>
    Public Function help() As String
        Dim s_output As String = ""
        If (Me.description IsNot Nothing) Then 'TODO: need to format the description correctly if its longer then the console window width buffer
            s_output += Me.description & vbCrLf & vbCrLf
        End If

            'print useage
            If (Me.syntax Is Nothing Or Me.syntax = "") Then
                Me.generateCMDformat()
            End If

            s_output += String.Format("Usage:{0,-8} {1}", Me.cmd, Me.syntax)

            'print params
            If (params.Count >= 1) Then
                s_output += vbCrLf & vbCrLf & "<Parameters>"
                For Each param As KeyValuePair(Of String, String) In params
                    s_output += vbCrLf & String.Format(" {0,-14}{1}", param.Key, param.Value)
                Next param
            End If

            'print args
            If (args.Count >= 1) Then
                s_output += vbCrLf & vbCrLf & "<Arguments>"
                For Each arg As KeyValuePair(Of String, String) In args
                    s_output += vbCrLf & String.Format(" {0,-14}{1}", arg.Key, arg.Value)
                Next arg
            End If
            Return s_output
    End Function
    Private Shared Function convert_arrayTo_kvp(ByRef array(,) As Object, ByRef _dict As SortedDictionary(Of Object, Object))
        Dim maxDim0 As Integer = UBound(array, 1)
        For i As Integer = 0 To maxDim0
            _dict.add(array(i, 0), array(i, 1))
        Next i
    End Function
    ' Accept changes to the Name & Age and return the values as a string
    Public Function _updateCommand(ByVal NewCmd As String, ByVal NewParams() As String, ByVal NewArgs() As String) As String
        Me.cmd = NewCmd
        Return Me.help
    End Function
    ''' <summary>
    ''' main caller for command
    ''' </summary>
    ''' <param name="params">string array of user passed parameters</param>
    ''' <param name="args">string array of user passed arguments</param>
    ''' <returns>bool of execution success</returns>
    ''' <remarks>must override</remarks>
    'Public MustOverride Function main(Optional ByRef params() As String = Nothing, Optional ByRef args() As String = Nothing)
#Region "Debuging Properties"
    ' The following properties are for getting information about the component
    ' for testing purposes only. Some information is retrieved using the
    ' AssemblyInfo class (defined in the AssemblyInfo.vb file).
    ' All the members are decorated with the Debug keyword to designate their
    ' testing status and to make them easy to find in IntelliSense.

    ' The CodeBase will return the physical path from which the 
    ' component is running.
    Public ReadOnly Property DebugCodeBase() As String
        Get
            Dim myType As Type = GetType(command)
            Return myType.Assembly.CodeBase
        End Get
    End Property
    ' Returns the assembly's fully qualified name
    Public ReadOnly Property DebugFQName() As String
        Get
            Dim myType As Type = GetType(command)
            Return myType.Assembly.GetName.FullName.ToString()
        End Get
    End Property
    ' Returns the date & time the current object instance was created.
    Public ReadOnly Property DebugCreationTime() As DateTime
        Get
            Return mdteCreationTime
        End Get
    End Property
    ' Returns the name of the machine that the object is running on.
    Public ReadOnly Property DebugHostName() As String
        Get
            Return System.Environment.MachineName
        End Get
    End Property
#End Region

    Private Sub convert_arrayTo_kvp(ByVal params As String(,), ByVal paramsValue As SortedDictionary(Of String, String))
        Throw New NotImplementedException
    End Sub

End Class